package fr.ece.ing4.si.MonteCarlo.Interface;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.ButtonGroup;

import fr.ece.ing4.si.MonteCarlo.Application.Config;
import fr.ece.ing4.si.MonteCarlo.Application.FileOpener;
import fr.ece.ing4.si.MonteCarlo.Application.MonteCarlo;

/**
 * 
 * @author matt
 * Window for the application
 */
public class Window extends JFrame
{
	/********** FILE **********/
	public String File = new String();
	
	/********** CONFIG **********/
	public Config simulation = new Config();
	public Map<String, Config> configurations = new HashMap<String, Config>();
	
	public String confName = new String();
	public JLabel configName = new JLabel("Configuration:");
	public JLabel Label1 = new JLabel("CallPutFlag: 0");
	public JLabel Label2 = new JLabel("Price: 0");
	public JLabel Label3 = new JLabel("Strike Price: 0");
	public JLabel Label4 = new JLabel("Interest Rate: 0");
	public JLabel Label5 = new JLabel("Time to Maturity: 0");
	public JLabel Label6 = new JLabel("Carry Rate Cost: 0");
	public JLabel Label7 = new JLabel("Underlying Asset Volatility: 0");
	public JLabel Label8 = new JLabel("Number of steps: 0");
	public JLabel Label9 = new JLabel("Number of simulations: 0");
	
	/********** SIMULATION **********/
	public double result = 0;
	public long timeResult = 0;
	public int coresNb = 0;
	public int poolSize = 0;
	
	public JLabel Type = new JLabel("Simulation:");
	public JLabel Result = new JLabel("Result: 0");
	public JLabel Time = new JLabel("Time: 0");
	public JLabel CoresNb = new JLabel("\t");
	public JLabel PoolSize = new JLabel("\t");
	
	/********** SIZE **********/
	public static int width = 900;
	public static int height = 350;
	
	/********** MENU **********/
	private JMenuBar menuBar = new JMenuBar();
	
	private JMenu FileOptions  = new JMenu("Files");
	private JMenuItem OpenFile = new JMenuItem("Open");
	
	private JMenu SimulationOptions = new JMenu("Simulation");
	private ButtonGroup SimulationChoice = new ButtonGroup();
	private JRadioButtonMenuItem SingleThreading = new JRadioButtonMenuItem("Single-Threading");
	private JRadioButtonMenuItem MultiThreading = new JRadioButtonMenuItem("Multi-Threading");
	
	/********** WINDOW **********/
	private JComboBox list = new JComboBox();
	
	private JPanel PaneCenter = new JPanel();
	private JPanel PanelConf = new JPanel();
	private JPanel PanelResult = new JPanel();
	
	private JPanel PaneSud = new JPanel();
	private JProgressBar bar = new JProgressBar(0,100);
	private JButton Launch= new JButton("launch");
	
	/********** Controller **********/
	private MonteCarlo Controller = new MonteCarlo();
	
	/********** FUNCTIONS **********/
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public Window() throws IOException
	{
		/***** WINDOW PARAMETERS INIT *****/
		this.setTitle("Monte Carlo Simulation");
		this.setSize(width, height);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLocationRelativeTo(null);
		this.setLayout(new BorderLayout());
		
		/***** WINDOW CONTENT INIT & DISPLAY *****/
		this.menuInitialization();
		this.windowInitialization();
		this.configInit();
		this.resultInit();
		this.setVisible(true);
	}
	
	/**
	 * Second constructor for the window. For testing.
	 * @param controller
	 * @throws IOException
	 */
	public Window(MonteCarlo controller) throws IOException
	{
		/***** WINDOW PARAMETERS INIT *****/
		this.Controller = controller;
		this.setTitle("Monte Carlo Simulation");
		this.setSize(width, height);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLocationRelativeTo(null);
		this.setLayout(new BorderLayout());
		
		/***** WINDOW CONTENT INIT & DISPLAY *****/
		this.menuInitialization();
		this.windowInitialization();
		this.configInit();
		this.resultInit();
		this.setVisible(true);
	}
	
	/**
	 * Initialization of the window.
	 */
	public void windowInitialization()
	{	
		/***** LIST *****/
		list.addItemListener(new ItemState());
		this.getContentPane().add(list, BorderLayout.NORTH);
		
		/***** CONFIG & RESULT *****/
		//PanelConf.setBackground(Color.ORANGE);
		//PanelResult.setBackground(Color.RED);
		PaneCenter.add(PanelConf);
		PaneCenter.add(PanelResult);
		this.getContentPane().add(PaneCenter, BorderLayout.CENTER);
		
		/***** PROGRESS BAR & LAUNCH BUTTON *****/
		bar.setValue(0);
		bar.setStringPainted(true);
		LaunchListener Listener =  new LaunchListener(this);
		Launch.addActionListener(Listener);
		Launch.setSize(20, 40);
		PaneSud.add(bar);
		PaneSud.add(Launch);
		this.getContentPane().add(PaneSud, BorderLayout.SOUTH);
		
	}
	
	/**
	 * Initialization of the menu
	 */
	public void menuInitialization()
	{
		/***** FILE TAB *****/
		FileOptionListener Listener = new FileOptionListener(this);
		OpenFile.addActionListener(Listener);
		FileOptions.add(OpenFile);
		menuBar.add(FileOptions);
		
		/***** SIMULATION TAB *****/
		SingleThreading.setSelected(true);
		SimulationChoice.add(SingleThreading);
		SimulationChoice.add(MultiThreading);
		SimulationOptions.add(SingleThreading);
		SimulationOptions.add(MultiThreading);
		SingleThreading.addItemListener(new ChoiceState());
		MultiThreading.addItemListener(new ChoiceState());
		menuBar.add(SimulationOptions);
		
		/***** ADD THE MENU BAR TO THE WINDOW *****/
		this.setJMenuBar(menuBar);
	}
	
	/**
	 * Initialization of the list of config
	 */
	public void listInitialization()
	{
		for(String name : configurations.keySet())
		{
			//System.out.println(name);
			list.addItem(name);
		}
	}
	
	/**
	 * Creation of the panel dedicated to the config
	 */
	public void configInit()
	{
		PanelConf.setPreferredSize(new Dimension(400,200));
		PanelConf.setLayout(new GridLayout(10,1));
		PanelConf.add(configName);
		PanelConf.add(Label1);
		PanelConf.add(Label2);
		PanelConf.add(Label3);
		PanelConf.add(Label4);
		PanelConf.add(Label5);
		PanelConf.add(Label6);
		PanelConf.add(Label7);
		PanelConf.add(Label8);
		PanelConf.add(Label9);
	}
	
	/**
	 * Actualization of the config panel
	 */
	public void displayConfig()
	{
		configName.setText("Configuration: " + this.confName);
		Label1.setText("CallPutFlag: " + simulation.CallPutFlag);
		Label2.setText("Price: " + simulation.Price_S);
		Label3.setText("Strike Price: " + simulation.StrikePrice_X);
		Label4.setText("Interest Rate: " + simulation.InterestRate_r);
		Label5.setText("Time to Maturity: " + simulation.TimeToMaturity_T);
		Label6.setText("Carry Rate Cost: " + simulation.CarryRateCost_b);
		Label7.setText("Underlying Asset Volatility: " + simulation.UnderlyingAssetVolatility_v);
		Label8.setText("Number of steps: " + simulation.nSteps);
		Label9.setText("Number of simulations: " + simulation.nSimulations);	
	}
	
	/**
	 * Creation of the panel dedicated to the results
	 */
	public void resultInit()
	{
		PanelResult.setPreferredSize(new Dimension(400,200));
		PanelResult.setLayout(new GridLayout(10,1));
		
		if(SingleThreading.isSelected())
		{
			Type.setText("Sequential Simulation");
		}
		else if(MultiThreading.isSelected())
		{
			Type.setText("Multi-Treaded Simulation");
			CoresNb.setText("Number of Cores: " + this.coresNb);
			PoolSize.setText("Pool Size: " + this.poolSize);
		}
		
		PanelResult.add(Type);
		PanelResult.add(CoresNb);
		PanelResult.add(PoolSize);
		PanelResult.add(Time);
		PanelResult.add(Result);
	}
	
	/**
	 * Actualization of the results panel.
	 */
	public void displayResult()
	{
		if(SingleThreading.isSelected())
		{
			Type.setText("Sequential Simulation");
			CoresNb.setText("\t");
			PoolSize.setText("\t");
		}
		else if(MultiThreading.isSelected())
		{
			Type.setText("Multi-Treaded Simulation");
			CoresNb.setText("Number of Cores: " + this.coresNb);
			PoolSize.setText("Pool Size: " + this.poolSize);
		}
		
		Time.setText("Time: " + timeResult);
		Result.setText("Result: " + result);
		
	}
	
	/**
	 * Listener of the list.
	 * @author matt
	 */
	class ItemState implements ItemListener
	{
		/**
		 * Happens when a config is selected in the list.
		 */
		public void itemStateChanged(ItemEvent e)
		{
			/***** SELECT THE CONFIG FOR THE SIMULATION FROM ALL THE CONFIG OF THE FILE *****/
			simulation = configurations.get(e.getItem().toString());
			confName=e.getItem().toString();
			result = 0;
			timeResult = 0;
			coresNb = 0;
			poolSize = 0;
			displayConfig();
			displayResult();
		}
	}
	
	/**
	 * Listener for the choice radio button.
	 * @author matt
	 *
	 */
	class ChoiceState implements ItemListener
	{
		public void itemStateChanged(ItemEvent e)
		{
			if(SingleThreading.isSelected())
			{
				Type.setText("Sequential Simulation");
			}
			else if(MultiThreading.isSelected())
			{
				Type.setText("Multi-Treaded Simulation");
			}
			result = 0;
			timeResult = 0;
			coresNb = 0;
			poolSize = 0;
			displayResult();
		}
	}
	
	/**
	 * Listener for the button allowing the search of a file.
	 * @author matt
	 *
	 */
	class FileOptionListener implements ActionListener
	{
		public Window win;
		
		public FileOptionListener(Window window)
		{
			win = window;
		}
		
		public void actionPerformed(ActionEvent arg0)
	    {
			JFileChooser fileChooser = new JFileChooser(".");
		    int choice = fileChooser.showOpenDialog(win); 
		    
		    bar.setValue(20);
		    
		    if (choice == JFileChooser.APPROVE_OPTION)
		    {
		    	File selection = fileChooser.getSelectedFile(); 
		    	win.File = selection.getAbsolutePath();
		    	//System.out.println(File);
		    	
		    	try
		    	{
					win.configurations = FileOpener.readFile(File);
					listInitialization();
					bar.setValue(50);
				}
		    	catch (IOException e)
		    	{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    }	
	    }      
	}
	
	/**
	 * Launching the app
	 * @author matt
	 *
	 */
	class LaunchListener implements ActionListener
	{
		public Window win;
		
		public LaunchListener(Window window)
		{
			win = window;
		}
		
		public void actionPerformed(ActionEvent arg0)
	    {
			try
			{	
				bar.setValue(80);
				if(SingleThreading.isSelected())
				{
						win.result = MonteCarlo.SingleThreadingSimulation(simulation);
						// win.result = MonteCarlo.result;
						win.timeResult = MonteCarlo.timeResult;
						
				}
				else if(MultiThreading.isSelected())
				{
						
						win.result = MonteCarlo.MultiThreadingSimulation(simulation);
						// win.result = MonteCarlo.result;
						win.coresNb = MonteCarlo.coresNb;
						win.poolSize = MonteCarlo.poolSize;
						win.timeResult = MonteCarlo.timeResult;
				}
				
				bar.setValue(100);
				displayResult();
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
	    }      
	}
	
	public String getFile()
	{
		return File;
	}
	
	public static void main()
	{
		try
		{
			Window window = new Window();
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
